bitkeeper revision 1.1676 (42a306a07UKpLq27_iCaJyxJBbKedg)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sun, 5 Jun 2005 14:05:20 +0000 (14:05 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sun, 5 Jun 2005 14:05:20 +0000 (14:05 +0000)
More console cleanups. The console ring now overwrites its tail when
it fills, rather than stop recording output. The guest serial output
is only allowed to half-fill the serial output buffer, and now
respects hypercall preemption requests.
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/libxc/xc.h
tools/libxc/xc_misc.c
tools/python/xen/lowlevel/xc/xc.c
xen/common/dom0_ops.c
xen/common/domain.c
xen/drivers/char/console.c
xen/drivers/char/serial.c
xen/include/public/dom0_ops.h
xen/include/xen/console.h
xen/include/xen/serial.h

index 29e642d4cb5ee738b2dbaa5a8e6053e41a55e24f..3c768f1a4af78e9f835910d79b47f03f2864330a 100644 (file)
@@ -388,8 +388,8 @@ int xc_physdev_pci_access_modify(int xc_handle,
                                  int enable);
 
 int xc_readconsolering(int xc_handle,
-                       char *str, 
-                       unsigned int max_chars, 
+                       char **pbuffer,
+                       unsigned int *pnr_chars, 
                        int clear);
 
 typedef dom0_physinfo_t xc_physinfo_t;
index 9ce8548709838cf5c27504a6a584a6b13890579e..40291bc3ef29f54d8471d390b07ecef6bb94ee40 100644 (file)
@@ -19,34 +19,35 @@ int xc_interface_close(int xc_handle)
     return close(xc_handle);
 }
 
-
-#define CONSOLE_RING_CLEAR 1
-
 int xc_readconsolering(int xc_handle,
-                       char *str, 
-                       unsigned int max_chars, 
+                       char **pbuffer,
+                       unsigned int *pnr_chars, 
                        int clear)
 {
     int ret;
     dom0_op_t op;
+    char *buffer = *pbuffer;
+    unsigned int nr_chars = *pnr_chars;
 
     op.cmd = DOM0_READCONSOLE;
-    op.u.readconsole.str = (unsigned long)str;
-    op.u.readconsole.count = max_chars;
-    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
+    op.u.readconsole.buffer = buffer;
+    op.u.readconsole.count  = nr_chars;
+    op.u.readconsole.clear  = clear;
 
-    if ( (ret = mlock(str, max_chars)) != 0 )
+    if ( (ret = mlock(buffer, nr_chars)) != 0 )
         return ret;
 
-    if ( (ret = do_dom0_op(xc_handle, &op)) >= 0 )
-        str[ret] = '\0';
+    if ( (ret = do_dom0_op(xc_handle, &op)) == 0 )
+    {
+        *pbuffer   = op.u.readconsole.buffer;
+        *pnr_chars = op.u.readconsole.count;
+    }
 
-    (void)munlock(str, max_chars);
+    (void)munlock(buffer, nr_chars);
 
     return ret;
 }    
 
-
 int xc_physinfo(int xc_handle,
                 xc_physinfo_t *put_info)
 {
@@ -64,7 +65,6 @@ int xc_physinfo(int xc_handle,
     return 0;
 }
 
-
 int xc_sched_id(int xc_handle,
                 int *sched_id)
 {
index 9b35ded02a25270704db139206fae5b41808eb1d..013fbe1fcc27eb32267f13bcbef7e536f11a7f8b 100644 (file)
@@ -678,7 +678,8 @@ static PyObject *pyxc_readconsolering(PyObject *self,
     XcObject *xc = (XcObject *)self;
 
     unsigned int clear = 0;
-    char         str[32768];
+    char         _str[32768], *str = _str;
+    unsigned int count = 32768;
     int          ret;
 
     static char *kwd_list[] = { "clear", NULL };
@@ -686,11 +687,11 @@ static PyObject *pyxc_readconsolering(PyObject *self,
     if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
         return NULL;
 
-    ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
+    ret = xc_readconsolering(xc->xc_handle, &str, &count, clear);
     if ( ret < 0 )
         return PyErr_SetFromErrno(xc_error);
 
-    return PyString_FromStringAndSize(str, ret);
+    return PyString_FromStringAndSize(str, count);
 }
 
 static PyObject *pyxc_physinfo(PyObject *self,
index 89654c7c453eca566da91b93ca28ddc77fea6431..4221c18c7e5f839732baf10a7f00f7f6a22c1924 100644 (file)
@@ -449,9 +449,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     
     case DOM0_READCONSOLE:
     {
-        ret = read_console_ring(op->u.readconsole.str, 
-                                op->u.readconsole.count,
-                                op->u.readconsole.cmd); 
+        ret = read_console_ring(
+            &op->u.readconsole.buffer, 
+            &op->u.readconsole.count,
+            op->u.readconsole.clear); 
+        copy_to_user(u_dom0_op, op, sizeof(*op));
     }
     break;
 
index c832a8341053b384ce297bf0dfece7968383c04a..127c57fe1763bc8fdb1a9ae22c3fea1d9a5f2ca4 100644 (file)
@@ -122,18 +122,9 @@ void domain_kill(struct domain *d)
 
 void domain_crash(void)
 {
-    struct domain *d = current->domain;
-
-    if ( d->domain_id == 0 )
-    {
-        show_registers(guest_cpu_user_regs());
-        panic("Domain 0 crashed!\n");
-    }
-
-#ifndef NDEBUG
+    printk("Domain %d (vcpu#%d) crashed on cpu#%d:\n",
+           current->domain->domain_id, current->vcpu_id, smp_processor_id());
     show_registers(guest_cpu_user_regs());
-#endif
-
     domain_shutdown(SHUTDOWN_crash);
 }
 
index db80be7983c7dce8256497c2367098f28287dba8..5ade44b42b4d1e8a027ca7be66d169640daad815 100644 (file)
@@ -16,6 +16,7 @@
 #include <xen/spinlock.h>
 #include <xen/console.h>
 #include <xen/serial.h>
+#include <xen/softirq.h>
 #include <xen/keyhandler.h>
 #include <xen/mm.h>
 #include <xen/delay.h>
@@ -42,13 +43,10 @@ boolean_param("sync_console", opt_sync_console);
 static int xpos, ypos;
 static unsigned char *video;
 
-#define CONSOLE_RING_SIZE 16392
-typedef struct console_ring_st
-{
-    char buf[CONSOLE_RING_SIZE];
-    unsigned int len;
-} console_ring_t;
-static console_ring_t console_ring;
+#define CONRING_SIZE 16384
+#define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
+static char conring[CONRING_SIZE];
+static unsigned int conringc, conringp;
 
 static char printk_prefix[16] = "";
 
@@ -218,23 +216,33 @@ static void putchar_console(int c)
 
 static void putchar_console_ring(int c)
 {
-    if ( console_ring.len < CONSOLE_RING_SIZE )
-        console_ring.buf[console_ring.len++] = (char)c;
+    conring[CONRING_IDX_MASK(conringp++)] = c;
+    if ( (conringp - conringc) > CONRING_SIZE )
+        conringc = conringp - CONRING_SIZE;
 }
 
-long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
+long read_console_ring(char **pstr, u32 *pcount, int clear)
 {
-    unsigned int len;
-    
-    len = (console_ring.len < count) ? console_ring.len : count;
-    
-    if ( copy_to_user((char *)str, console_ring.buf, len) )
-        return -EFAULT;
+    char *str = *pstr;
+    u32 count = *pcount;
+    unsigned int p, q;
+    unsigned long flags;
 
-    if ( cmd & CONSOLE_RING_CLEAR )
-        console_ring.len = 0;
-    
-    return len;
+    /* Start of buffer may get overwritten during copy. So copy backwards. */
+    for ( p = conringp, q = count; (p > conringc) && (q > 0); p--, q-- )
+        if ( put_user(conring[CONRING_IDX_MASK(p-1)], (char *)str+q-1) )
+            return -EFAULT;
+
+    if ( clear )
+    {
+        spin_lock_irqsave(&console_lock, flags);
+        conringc = conringp;
+        spin_unlock_irqrestore(&console_lock, flags);
+    }
+
+    *pstr   = str + q;
+    *pcount = count - q;
+    return 0;
 }
 
 
@@ -301,13 +309,44 @@ static void serial_rx(char c, struct cpu_user_regs *regs)
     __serial_rx(c, regs);
 }
 
+long guest_console_write(char *buffer, int count)
+{
+    char kbuf[128];
+    int kcount;
+
+    while ( count > 0 )
+    {
+        while ( serial_tx_space(sercon_handle) < (SERIAL_TXBUFSZ / 2) )
+        {
+            if ( hypercall_preempt_check() )
+                break;
+            cpu_relax();
+        }
+
+        if ( hypercall_preempt_check() )
+            return hypercall3_create_continuation(
+                __HYPERVISOR_console_io, CONSOLEIO_write, count, buffer);
+
+        kcount = min_t(int, count, sizeof(kbuf)-1);
+        if ( copy_from_user(kbuf, buffer, kcount) )
+            return -EFAULT;
+        kbuf[kcount] = '\0';
+
+        serial_puts(sercon_handle, kbuf);
+
+        buffer += kcount;
+        count  -= kcount;
+    }
+
+    return 0;
+}
+
 long do_console_io(int cmd, int count, char *buffer)
 {
-    char *kbuf;
-    long  rc;
+    long rc;
 
 #ifndef VERBOSE
-    /* Only domain-0 may access the emergency console. */
+    /* Only domain 0 may access the emergency console. */
     if ( current->domain->domain_id != 0 )
         return -EPERM;
 #endif
@@ -315,17 +354,7 @@ long do_console_io(int cmd, int count, char *buffer)
     switch ( cmd )
     {
     case CONSOLEIO_write:
-        if ( count > (PAGE_SIZE-1) )
-            count = PAGE_SIZE-1;
-        if ( (kbuf = (char *)alloc_xenheap_page()) == NULL )
-            return -ENOMEM;
-        kbuf[count] = '\0';
-        rc = count;
-        if ( copy_from_user(kbuf, buffer, count) )
-            rc = -EFAULT;
-        else
-            serial_puts(sercon_handle, kbuf);
-        free_xenheap_page((unsigned long)kbuf);
+        rc = guest_console_write(buffer, count);
         break;
     case CONSOLEIO_read:
         rc = 0;
index 51cfaa56eb9068c9fdd94af0344e1433612913e7..a59146da0a0d7e941475e8484e5492cb08dead0d 100644 (file)
@@ -317,6 +317,14 @@ void serial_end_sync(int handle)
     spin_unlock_irqrestore(&port->lock, flags);
 }
 
+int serial_tx_space(int handle)
+{
+    struct serial_port *port = &com[handle & SERHND_IDX];
+    if ( handle == -1 )
+        return SERIAL_TXBUFSZ;
+    return SERIAL_TXBUFSZ - (port->txbufp - port->txbufc);
+}
+
 void serial_init_preirq(void)
 {
     int i;
index 4c3d5271a2f8b52da31268127fa8bedf9ca8b354..0768b8c6ae6d4a4e8a4e720d3f62fae31dd87010 100644 (file)
@@ -164,9 +164,11 @@ typedef struct {
  */
 #define DOM0_READCONSOLE      19
 typedef struct {
-    memory_t str;
-    u32      count;
-    u32      cmd;
+    /* IN variables. */
+    u32      clear;        /* Non-zero -> clear after reading. */
+    /* IN/OUT variables. */
+    char    *buffer;       /* In: Buffer start; Out: Used buffer start */
+    u32      count;        /* In: Buffer size;  Out: Used buffer size  */
 } dom0_readconsole_t;
 
 /* 
index 4295a41de6b775cf09d2a52b565a31f608ca5922..12028cdc97b3ba151d2a3104ff87bfed9c7fe2b5 100644 (file)
@@ -13,8 +13,7 @@ extern spinlock_t console_lock;
 
 void set_printk_prefix(const char *prefix);
 
-#define CONSOLE_RING_CLEAR 1
-long read_console_ring(unsigned long, unsigned int, unsigned int);
+long read_console_ring(char **, u32 *, int);
 
 void init_console(void);
 void console_endboot(int disable_vga);
index 9a1dd60cf4ad8acf173755cb8f3f1df2fec7209f..8d5f246ab20a1ea5be9ace514edfccd7043a90a8 100644 (file)
@@ -96,6 +96,9 @@ void serial_force_unlock(int handle);
 void serial_start_sync(int handle);
 void serial_end_sync(int handle);
 
+/* Return number of bytes headroom in transmit buffer. */
+int serial_tx_space(int handle);
+
 /*
  * Initialisation and helper functions for uart drivers.
  */